
// 浅复制，只做第一层复制
export const shallowCopy = (src) => {
    var dst = {};
    for (var prop in src) {
      if (src.hasOwnProperty(prop)) {
        dst[prop] = src[prop];
      }
    }
    if (Object.prototype.toString.call(src) == "[object Array]") {
      dst = Object.values(dst);
    }
    return dst;
  };
  
  /**
   * 深拷贝
   * @param {*} obj 拷贝对象(object or array)
   * @param {*} cache 缓存数组
   */
  export const deepCopy = (obj, cache = []) => {
    // typeof [] => 'object'
    // typeof {} => 'object'
    if (obj === null || typeof obj !== "object") {
      return obj;
    }
    // 如果传入的对象与缓存的相等, 则递归结束, 这样防止循环
    /**
     * 类似下面这种
     * var a = {b:1}
     * a.c = a
     * 资料: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Cyclic_object_value
     */
    const hit = cache.filter((c) => c.original === obj)[0];
    if (hit) {
      return hit.copy;
    }
  
    const copy = Array.isArray(obj) ? [] : {};
    // 将copy首先放入cache, 因为我们需要在递归deepCopy的时候引用它
    cache.push({
      original: obj,
      copy,
    });
    Object.keys(obj).forEach((key) => {
      copy[key] = deepCopy(obj[key], cache);
    });
  
    return copy;
  };

  
/**
 * @desc 函数防抖
 * @param func 函数
 * @param wait 延迟执行毫秒数
 * @param immediate true 表立即执行，false 表非立即执行
 */
export function debounce(func, wait, immediate) {
    var timeout;
    return function () {
      let context = this;
      let args = arguments;
  
      if (timeout) clearTimeout(timeout);
      if (immediate) {
        var callNow = !timeout;
        timeout = setTimeout(() => {
          timeout = null;
        }, wait);
        if (callNow) func.apply(context, args);
      } else {
        timeout = setTimeout(function () {
          func.apply(context, args);
        }, wait);
      }
    };
  }
  
  /**
   * @desc 函数节流
   * @param func 函数
   * @param wait 延迟执行毫秒数
   * @param type 1 表时间戳版，2 表定时器版
   */
  export function throttle(func, wait, type) {
    if (type === 1) {
      var previous = 0;
    } else if (type === 2) {
      var timeout;
    }
    return function () {
      let context = this;
      let args = arguments;
      if (type === 1) {
        let now = Date.now();
  
        if (now - previous > wait) {
          func.apply(context, args);
          previous = now;
        }
      } else if (type === 2) {
        if (!timeout) {
          timeout = setTimeout(() => {
            timeout = null;
            func.apply(context, args);
          }, wait);
        }
      }
    };
  }
  